package com.security.exception;

import com.security.domain.bo.R;
import com.security.utils.ResponseUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.io.IOException;

/**
 * 全局异常处理器，只针对 Controller 层异常处理
 * 注意：如果在 Controller 层抛出的异常是 RuntimeException 类型，会被 Spring MVC 捕获并处理，
 * 但如果是其他类型的异常，需要在 Controller 层手动抛出，才能被全局异常处理器捕获
 *
 * @author DblSun
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    @Resource
    private HttpServletResponse response;

    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public void handleMyException(AccessDeniedException e) throws IOException {
        log.error("用户权限不足异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_FORBIDDEN, "用户权限不足"));
    }

    @ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public void handleMyException(AuthenticationCredentialsNotFoundException e) throws IOException {
        log.error("Token 过期异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_FORBIDDEN, "Token 已过期"));
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public void handleMyException(RuntimeException e) throws IOException {
        log.error("运行时异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()));
    }

    @ExceptionHandler(ArithmeticException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handleMyException(ArithmeticException e) throws IOException {
        log.error("算术异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()));
    }

    @ExceptionHandler(NoResourceFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public void handleNoResourceException(NoResourceFoundException e) throws IOException {
        log.error("资源异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_NOT_FOUND, "请求路径无效"));

    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleMyException(Exception e) throws IOException {
        log.error("其他异常信息：{}", e.getMessage());
        ResponseUtil.sendResponse(response, R.error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器内部错误"));
    }
}
